<?php

/**
 * GenProg Lenguaje de Consultas Basado en SQL
 *
 *
 * @author      Carlos Peña <crash.madover@gmail.com>
 * @package     application.libraries.orm.sql.sql
 * @copyright   (c) 2013, GenProg
 * @version     v 1.0
 */
class Sql {
  // -------------------------------------------------------------------------------------

  /**
   * Auxiliar de Consulta
   * @var       string
   */
  private $sCon = '';

  // -------------------------------------------------------------------------------------

  /**
   * Tabla Principal de Conexion
   * @var       string
   */
  public $tabla = '';

  // -------------------------------------------------------------------------------------

  /**
   * Campos de SeleccionArreglo de Tablas
   * @var       string
   */
  private $set = '*';

  // -------------------------------------------------------------------------------------

  /**
   * Selecion Simple del Codigo
   * @var       string
   */
  private $selecinar = '';

  // -------------------------------------------------------------------------------------

  /**
   * Unir Varias Tablas
   * @var       string
   */
  private $union = '';

  // -------------------------------------------------------------------------------------

  /**
   * Donde Elementos
   * @var       string
   */
  private $donde = '';

  // -------------------------------------------------------------------------------------

  /**
   * Grupo de Elementos
   * @access    private
   * @var       string
   */
  private $grupo = '';

  // -------------------------------------------------------------------------------------

  /**
   * Parametros
   * @access    private
   * @var       integer
   */
  private $param = 0;

  // -------------------------------------------------------------------------------------

  /**
   * Arreglo de Tablas
   * @access    public
   * @var       array()
   */
  public $crear = array();

  // -------------------------------------------------------------------------------------

  /**
   * Contador de Modelos
   * @access    private
   * @var       integer
   */
  private $iModelo = 1;

  // -------------------------------------------------------------------------------------

  /**
   * Control de Alter Tables
   * @access    public
   * @var       array()
   */
  public $cambiar = array();

  // -------------------------------------------------------------------------------------

  /**
   * Control de Insert Gp_SClavesForaneas
   * @access    public
   * @var       array()
   */
  public $clave_foraneas = array();

  // -------------------------------------------------------------------------------------

  /**
   * Control de Alter Tables
   * @access    public
   * @var       array()
   */
  public $seguridad = array();

  // -------------------------------------------------------------------------------------

  /**
   * Class Modelo de Datos GPDL
   * @access  private
   * @var     string
   */
  private $Modelo = null;

  // -------------------------------------------------------------------------------------

  /**
   * Constructor de la Class
   * @access      public
   * @param       string      Class Opcional
   * @return      string      Texto del Modelo
   */
  function __construct($sModelo = '') {
    $this->Modelo = $sModelo;
  }

  // -------------------------------------------------------------------------------------

  /**
   * Instanciar Modelo
   * @access      public
   * @param       string      Class Opcional
   * @return      string      Texto del Modelo
   */
  public function CargarModelo($sModelo = '') {
    $this->Modelo = $sModelo;
  }

  // -------------------------------------------------------------------------------------

  /**
   * Crear Base de Datos
   *
   */
  function _CreateBD() {
    $sCon = 'CREATE DATABASE ';
  }

  // -------------------------------------------------------------------------------------

  /**
   * Generar Conjunto de Tablas desde Archivos
   *
   * @access      public
   * @return      boolean       Verdadero
   */
  public function GenerarTablas() {
    $dir = APPPATH . 'models/' . MODEL;
    if (is_dir($dir)) {
      if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
          if (!is_dir($file)) {
            $pr = explode('.', $file);
            $Class = $pr[0];
            include_once ($dir . $file);
            $oModelo = new $Class();
            $this->seguridad[] = '(\'' . $oModelo->tabla . '\',\'' . $Class . '\',\'' . $oModelo->prefijo . '\')';
            $this->crear[] = $this->_CreateTB($oModelo->tabla, $oModelo->struc['cmp'], $oModelo->dtd, $oModelo->prefijo);
          }
        }
        closedir($dh);
      }
    }
    return TRUE;
  }

  // -------------------------------------------------------------------------------------

  /**
   * Generar Conjunto de Tablas
   *
   * @access      public
   * @param       class      Modelo de Datos
   * @return      boolean    Verdadero
   */
  public function _GenerarTB($sMod = null) {
    if ($this->param == 0)
      $this->crear[] = $this->_CreateTB($sMod->tabla, $sMod->struc['cmp'], $sMod->dtd, $sMod->prefijo);

    $this->seguridad[] = '(\'' . $sMod->tabla . '\',\'' . get_class($sMod) . '\',\'' . $sMod->prefijo . '\')';
    if (isset($sMod->struc['join'])) {
      foreach ($sMod->struc['join'] as $Clv => $Val) {
        include_once (APPPATH . 'models/' . MODEL . strtolower($Clv) . '.php');
        $this->param++;
        $Class = strtolower($Clv);
        $oModelo = new $Class();
        $this->seguridad[] = '(\'' . $oModelo->tabla . '\',\'' . $Class . '\',\'' . $oModelo->prefijo . '\')';
        $this->crear[] = $this->_CreateTB($oModelo->tabla, $oModelo->struc['cmp'], $oModelo->dtd, $oModelo->prefijo);
        if (isset($oModelo->struc['join'])) {
          $this->_GenerarTB($oModelo);
        }
      }
    }
    return TRUE;
  }

  // -------------------------------------------------------------------------------------

  /**
   * Crear Tabla de Datos InnoDB y MyIsam
   *
   * @access      public
   * @param       string      Nombre de la Tabla (Innodb, MyIsam)
   * @param       array()     Arreglo de Campo Clave y Valor
   * @param       string      Descripcion de la tabla
   * @param       string      Prefijo de la Tabla Con Campos
   * @return      string      Query SQL
   */
  private function _CreateTB($tabla = null, $cmp = array(), $dtd = '', $pre = '') {
    $arr = array();
    // Formato del Campo
    $arrA = array();
    // En los Casos PRIMARY, INDEX, FORINGE KEY, FULLTEXT
    $sClaves = '';
    // Creando lineas de Tablas
    $sCadena = '';
    //Constuyendo lineas del Create
    $sCreate = 'CREATE TABLE IF NOT EXISTS ' . $tabla . ' (';
    $sComentario = '';
    $sTipo = '';
    $i = 0;
    $iCmp = count($cmp);
    $pre .= '_';

    foreach ($cmp as $sClv => $sVal) {
      $sAuto = '';
      //Palabras reservadas para el Query y Otros
      $i++;

      if (isset($sVal['comentario'])) {
        $sComentario = 'COMMENT \'' . $sVal['comentario'] . '\'';
      }
      if (isset($sVal['clave'])) {

        if ($sVal['clave'] == 'KEY') {
          $sClaves .= ', KEY (' . $pre . $sClv . ')';
        } else {
          $sClaves .= ', PRIMARY KEY (' . $pre . $sClv . ')';
        }
      }

      if (isset($sVal['incremento'])) {
        $sAuto = 'AUTO_INCREMENT';
      }
      $sTipo = 'VARCHAR (32) NOT NULL';
      if (isset($sVal['tipo'])) {
        $sTipo = $sVal['tipo'];
        if ('DATE' != $sTipo && 'TIMESTAMP' != $sTipo) {
          if (isset($sVal['longitud'])) {
            $sTipo .= ' (' . $sVal['longitud'] . ') NOT NULL ' . $sAuto;
          } else {
            if ('DECIMAL' == $sTipo) {
              $sTipo .= ' (10,2) NOT NULL';
            } else {
              if ($sTipo != 'TEXT') {

                $sTipo .= ' (10) NOT NULL ' . $sAuto;
              } else {
                $sTipo .= ' NOT NULL ' . $sAuto;
              }
            }
          }
        } elseif ($sTipo == 'TIMESTAMP') {
          $sTipo .= ' NOT NULL DEFAULT CURRENT_TIMESTAMP';
        }
      }

      $sCreate .= ' ' . $pre . $sClv . ' ' . $sTipo . ' ' . $sComentario;
      if ($i < $iCmp) {
        $sCreate .= ',';
      }
      $sComentario = '';

      if (isset($sVal['clave_foranea'])) {
        $Class = $sVal['clave_foranea'][0];
        include_once (APPPATH . 'models/' . MODEL . $sVal['clave_foranea'][0] . '.php');
        $Class = $sVal['clave_foranea'][0];
        $oModelos = new $Class();
        $sClaveForanea = $sVal['clave_foranea'][1];
        $sRef = $oModelos->tabla;
        $sClaveForaneaPrefijo = $oModelos->prefijo . '_' . $sClaveForanea;
        $this->clave_foraneas[] = "('" . $tabla . "','" . $pre . $sClv . "','" . $sRef . "','" . $sClaveForaneaPrefijo . "')";
        $this->cambiar[] = 'ALTER IGNORE TABLE `' . $tabla . '` ADD CONSTRAINT `' . $tabla . '_ibfk_' . $i . '` FOREIGN KEY ( `' . $pre . $sClv . '` ) REFERENCES `' . $sRef . '` (`' . $sClaveForaneaPrefijo . '`) ON DELETE CASCADE ON UPDATE CASCADE ;';
      }
    }// Fin del Repita

    $sCreate .= $sClaves . ') ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT=\'\';';
    return $sCreate;
  }

  // --------------------------------------------------------------------------

  /**
   * Insertar elementos
   */
  public function Insertar($aObjeto = array()) {
    
  }

  // --------------------------------------------------------------------------
  // GENERACIONES DE BUSQUEDAS
  // --------------------------------------------------------------------------

  /**
   * Crear Select
   *
   * @access      public
   * @return      string      (SQL)
   */
  public function Select($set = '') {
    if($set != ''){
      $this->set = $set;
    }
    $sCon = 'SELECT ' . $this->set . ' FROM ' . $this->tabla . ' ';
    return $sCon;
  }

  // --------------------------------------------------------------------------

  /**
   * Crear Metodo Set del SQL Crea los Campos
   *
   * @access      public
   * @param       string      Nombre de la Tabla
   * @param       string      Arreglo de Campos
   * @return      boolean     (SQL)
   */
  public function Set($tabla = '', $set = array()) {
    if ($this->set != '') {
      $this->set .= ',';
    }
    $iCan = count($set);
    //Cantidad de Registros
    $i = 0;
    foreach ($set as $sVal) {
      $i++;
      $this->set .= $tabla . '.' . $sVal;
      if ($iCan == $i) {
        $this->set .= ',';
      }
    }
    return true;
  }

  // --------------------------------------------------------------------------

  /**
   * Crear Join
   *
   * @access public
   * @param       string      Nombre de la Tabla
   * @param       array()     Arreglo de Uniones
   * @return      string      (SQL)
   */
  public function Join($tabla, $join = array(), $pre = '') {
    $sCon = '';
    $sQ = '';
    $pre .= '_';
    foreach ($join as $Clv => $Val) {
      if (!isset($Val['tipo'])) {
        $mdl = "T_" . $this->param++;
        include_once (APPPATH . 'models/' . MODEL . strtolower($Clv) . '.php');
        $Class = $Clv;
        $oModelo = new $Class();
        if (isset($oModelo->struc['join'])) {
          if (count($oModelo->struc['join']) > 0) {
            $sQ .= $this->Join($oModelo->tabla, $oModelo->struc['join'], $oModelo->prefijo);
          }
        }
        $join = ' JOIN ';
        if (!isset($Val['relacion']) || $Val['relacion'] == 'cero-a-muchos' || $Val['relacion'] == 'cero-a-uno') {
          $join = ' LEFT JOIN ';
        }
        $sCon .= $join . $oModelo->tabla;

        foreach ($Val as $sC => $sV) {
          if ($sC != 'relacion' && $sC != 'dtd' && $sC != 'inverso') {
            $sCon .= ' ON ' . $oModelo->tabla . '.' . $oModelo->prefijo . '_' . $sC . '=' . $tabla . '.' . $pre . $sV;
          }
        }
      }
      unset($mdl);
    }

    return $sCon . $sQ;
  }

  // ------------------------------------------------------------------

  /**
   * Crear WHERE SQL
   *
   * @access      public
   * @param       array()     Where
   * @return      string      (SQL)
   */
  public function Where($where = array()) {
    $this->sCon .= ' WHERE id = \'' . $where['id'] . '\'';
    return $this->sCon;
  }

  // --------------------------------------------------------------------

  /**
   * Crear GROUP BY SQL
   *
   * @access      public
   * @param       array()     Arreglo de Grupos
   * @return      string      (SQL)
   */
  public function Group($group = array()) {
    
  }

  // --------------------------------------------------------------------

  /**
   * Generar Codigo SQL
   *
   * @access      public
   * @return      string      SQL
   */
  public function ObtenerSeguridad($aInsertar = array()) {
    if (count($aInsertar) == 0) {
      $sInsertar = 'INSERT IGNORE INTO Gp_SEsquema (tabl,mode,pref) VALUES ';
      $iCon = count($this->seguridad);
      $i = 0;
      foreach ($this->seguridad as $key => $value) {
        ++$i;
        if ($iCon != $i) {
          $sInsertar .= $value . ',';
        } else {
          $sInsertar .= $value;
        }
      }
    } else {//Caso de que insertar > 0
      $sInsertar = ' ';
    }

    return $sInsertar . ';';
  }

  public function ObetenerClavesForaneas($Clave = array()) {
    if (count($Clave) == 0) {
      $sClave = 'INSERT IGNORE INTO Gp_SClavesForaneas (`tabla`,`columna`,`ref_tabla`, `ref_columna`) VALUES';
      $iCon = count($this->clave_foraneas);
      $i = 0;
      foreach ($this->clave_foraneas as $key => $value) {
        ++$i;
        if ($iCon != $i) {
          $sClave .= $value . ',';
        } else {
          $sClave .= $value;
        }
      }
    } else {//Caso de que insertar > 0
      $sClave = ' ';
    }

    return $sClave . ';';
  }

  // --------------------------------------------------------------------

  /**
   * Esquema de la base de datos Plantilla
   * Permite controlar y mapear las tablas a un esquema generico
   * Problemas entre la GUI y BD
   */
  public function Generar_Esquema_Seguridad() {
    $sCrear[] = "CREATE TABLE IF NOT EXISTS `Gp_SEsquema` (
            `tabl` varchar(32) NOT NULL COMMENT 'Nombre de la Tabla',
            `mode` varchar(32) NOT NULL COMMENT 'Nombre del Modelo',
            `pref` varchar(4) NOT NULL COMMENT 'Prefijo de la tabla',
            PRIMARY KEY (`pref`,`tabl`)
            ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Esquema de modelos y base de datos';";

    $sCrear[] = "CREATE TABLE IF NOT EXISTS `Gp_SClavesForaneas` (
            `tabla` varchar(64) NOT NULL COMMENT 'Tabla Origen De Datos',
            `columna` varchar(64) NOT NULL COMMENT 'Columna Origen',
            `ref_tabla` varchar(64) NOT NULL COMMENT 'Referencia Tabla',
            `ref_columna` varchar(64) NOT NULL COMMENT 'ReferenciaColumna Origen'
            ) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Esquema de Claves Foraneas';";
    return $sCrear;
  }

  // --------------------------------------------------------------------

  /**
   * Generar Codigo SQL
   *
   * @access      public
   * @return      string      SQL
   */
  public function Generar($set = '') {

    $sModelo = $this->Modelo;
    include_once (APPPATH . 'models/' . MODEL . strtolower($sModelo) . '.php');
    $oModelo = new $sModelo();
    $this->tabla = $oModelo->tabla;
    $this->sCon = $this->Select($set);
    if (isset($oModelo->struc['join'])) {
      $this->sCon .= $this->Join($this->tabla, $oModelo->struc['join'], $oModelo->prefijo);
    }

    return $this->sCon;
  }

}

?>